/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using DaveSexton.DocProject.Resources;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;

namespace DaveSexton.DocProject
{
	public abstract class VSCommand : System.ComponentModel.Component
	{
		#region Public Properties
		public string UniqueName
		{
			get
			{
				return DocProjectEnvironment.ProgId + "." + Name;
			}
		}

		/// <summary>
		/// When implemented by a derived class, gets the unique name of the command.  The name must be unqiue among all commands in Visual Studio and cannot contain any spaces.
		/// </summary>
		public abstract string Name { get; }

		[CLSCompliant(false)]
		public virtual vsCommandStatus Status
		{
			get
			{
				return vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
			}
		}

		[CLSCompliant(false)]
		public virtual vsCommandStyle Style
		{
			get
			{
				return vsCommandStyle.vsCommandStylePict;
			}
		}

		[CLSCompliant(false)]
		public virtual vsCommandControlType ControlType
		{
			get
			{
				return vsCommandControlType.vsCommandControlTypeButton;
			}
		}

		/// <summary>
		/// Optional collection of <see cref="EnvDTE80.ContextGuids"/> values that indicate the IDE states in which 
		/// the command will be visible.
		/// </summary>
		public virtual ICollection<Guid> ContextGuids
		{
			get
			{
				return new Guid[0];
			}
		}

		public abstract bool UseOfficeBitmapResourceId { get; }

		public virtual int OfficeBitmapResourceId
		{
			get
			{
				return 59;		// smiley
			}
		}

		public virtual System.Drawing.Image Image
		{
			get
			{
				return null;
			}
		}

		public virtual System.Drawing.Color ImageTransparencyKey
		{
			get
			{
				return System.Drawing.Color.Empty;
			}
		}

		public string Text
		{
			get
			{
				return GetStatusText(Status);
			}
		}

		public virtual string Tooltip
		{
			get
			{
				return Text;
			}
		}

		[CLSCompliant(false)]
		public CommandBarControl Control
		{
			get
			{
				return control;
			}
			internal set
			{
				control = value;
			}
		}

		[CLSCompliant(false)]
		public Command Command
		{
			get
			{
				return command;
			}
			internal set
			{
				command = value;
			}
		}
		#endregion

		#region Private / Protected
		private CommandBarControl control;
		private Command command;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="VSCommand" /> class for derived classes.
		/// </summary>
		protected VSCommand()
		{
		}
		#endregion

		#region Methods
		[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand,
			Flags = System.Security.Permissions.SecurityPermissionFlag.Infrastructure)]
		public override object InitializeLifetimeService()
		{
			return null;
		}

		public virtual string GetStatusText(object status)
		{
			return Name;
		}

		public abstract object Execute(object option, object argument);
		#endregion

		#region Events
		private readonly object CommandCreatedEventLock = new object();
		private EventHandler CommandCreatedEvent;

		/// <summary>
		/// Event raised after the <see cref="Command"/> and <see cref="Control"/> have been created.
		/// </summary>
		public event EventHandler CommandCreated
		{
			add
			{
				lock (CommandCreatedEventLock)
				{
					CommandCreatedEvent += value;
				}
			}
			remove
			{
				lock (CommandCreatedEventLock)
				{
					CommandCreatedEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="CommandCreated" /> event.
		/// </summary>
		/// <param name="e"><see cref="EventArgs" /> object that provides the arguments for the event.</param>
		protected internal virtual void OnCommandCreated(EventArgs e)
		{
			EventHandler handler = null;

			lock (CommandCreatedEventLock)
			{
				handler = CommandCreatedEvent;
			}

			if (handler != null)
				handler(this, e);
		}
		#endregion
	}
}
